/***************************************************************************
                        mirrors.c  -  Part of gltris
                             -------------------
    begin                : May 2001
    copyright            : (C) 2001 by David Delbecq (Alias Tchize)
    email                : david.delbecq@usa.net
 ***************************************************************************/
/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

/****************************************************************************
* This module is reponsible for handling some mirrors concepts:             *
*    - Drawing the outside of a mirror                                      *
*    - Preparing the matrix for a mirror operation                          *
*    - Updating the stencil according to mirrors recursions                 *
****************************************************************************/
#include "os_depend.h"
#include <GL/gl.h>
#include "mirrors.h"
TMirror mirrors[MaxMirrors];

/*
This fonction refresh the mirror so to uniform the stencil
values. stencil must a least be 1 (eq. it must be a mirror stencil).
Note: stencil values of 0 are reserved for primal scene, higher values
      depend on the actual recursion depth.
*/
void RefreshMirror (int mirrornumber, int stencil)
     {
     glPopMatrix (); /*Go back to the mirror source.*/
     glPushMatrix (); /*Leave matrix stack unchanged*/
     glStencilFunc (GL_GEQUAL,stencil,255); /*Stencil update*/
     glStencilOp (GL_KEEP,GL_KEEP,GL_REPLACE);
     mirrors[mirrornumber].stencildrawer();

     glScalef (1.0,1.0,-1.0); /*Mirrorize the z-coordinate*/
     glTranslatef (0.0,0.0,mirrors[mirrornumber].distance); /*Go inside the mirror*/
     glRotatef (mirrors[mirrornumber].beta,-1.0,0.0,0.0);
     glRotatef (mirrors[mirrornumber].alpha,0.0,-1.0,0.0);
     }
/*
 This function draw a mirror with it's stencil and update
 the stencil depth functions. It also updates the modelview
 matrix so that the center is put inside the mirror with
 vector's coordinates mirrored. Don't forget to take care of
 objects going through the mirrors!!!! Every object of the scene
 is recommended to be in the same side of the mirror
*/
void DrawMirror (int mirrornumber, int stencil, int oldstencil)
     {
     GLfloat size=5.0;
     /* 1st part: achieve a coordinate system where z is normal to the mirror*/
     glRotatef (mirrors[mirrornumber].alpha,0.0,1.0,0.0);
     glRotatef (mirrors[mirrornumber].beta,1.0,0.0,0.0);
     glTranslatef (0.0,0.0,-mirrors[mirrornumber].distance);
     /* 2nd part: draw the mirror with stencil, scale for z inversion (z-mirroring)*/
     glStencilFunc (GL_EQUAL,stencil,oldstencil);/*Mask so to handle old values*/
     glStencilOp (GL_KEEP,GL_KEEP,GL_REPLACE);
     mirrors[mirrornumber].stencildrawer();

     /*     glPushAttrib (GL_ALL_ATTRIB_BITS);
          glDepthMask (GL_FALSE);
          glColorMask (GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
          glBegin (GL_QUADS);
               glVertex3f (-size,-size,0.0);
               glVertex3f (size,-size,0.0);
               glVertex3f (size,size,0.0);
               glVertex3f (-size,size,0.0);
          glEnd ();
          glPopAttrib ();
          glBegin (GL_LINE_LOOP);
               glDisable (GL_TEXTURE_2D);
               glDisable (GL_LIGHTING);
               glColor3f (1.0,1.0,1.0);
               glVertex3f (-size,-size,0.0);
               glVertex3f (size,-size,0.0);
               glVertex3f (size,size,0.0);
               glVertex3f (-size,size,0.0);
          glEnd();  */

     glStencilOp (GL_KEEP,GL_KEEP,GL_KEEP);
     glStencilFunc (GL_EQUAL,stencil,stencil);
     /* 3rd part: go back to the mirror-side origin*/
     glPushMatrix ();
     glScalef (1.0,1.0,-1.0); /*Mirrorize the z-coordinate*/
     glTranslatef (0.0,0.0,mirrors[mirrornumber].distance); /*Go inside the mirror*/
     glRotatef (mirrors[mirrornumber].beta,-1.0,0.0,0.0);
     glRotatef (mirrors[mirrornumber].alpha,0.0,-1.0,0.0);
     }
/*
The purpose of this fonction is to erase any track of the mirror in the stencil buffer
stencil is the limit stencil value we have to handle for the mirror we are killing
oldstencil is the stencil value we have to give him (usually: mirror's parent stencil value
*/
void CleanMirror (int mirrornumber, int stencil, int oldstencil)
     {
     glPopMatrix ();
     glStencilFunc (GL_EQUAL,oldstencil,oldstencil);/*Mask so to handle old values*/
     glStencilOp (GL_KEEP,GL_KEEP,GL_REPLACE);
     mirrors[mirrornumber].stencildrawer();   /*Ask for mirror redrawing to kill upper stencil values*/
     glStencilOp (GL_KEEP,GL_KEEP,GL_KEEP);
     glTranslatef (0.0,0.0,mirrors[mirrornumber].distance); /*Go inside the mirror*/
     glRotatef (mirrors[mirrornumber].beta,-1.0,0.0,0.0);
     glRotatef (mirrors[mirrornumber].alpha,0.0,-1.0,0.0);
     }

